import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:geomancy/models/base_model.dart';
import 'package:geomancy/providers/user_provider.dart';
import 'package:geomancy/tools/auth_login.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:lunar/lunar.dart';
import 'package:vibration/vibration.dart';

class Utils {
  ///判断用户是否登录
  static bool getLoginState(BuildContext context) {
    final String? token = context.read<UserProvider>().getToken;
    if (token == null || token == '') {
      AliAuthLoginTools.login(context);
      return false;
    }
    ///未注册(根据资料是否填写完来判断，最后一步是头像，这个可以跳过)
    final User? user = context.read<UserProvider>().getUserInfo;
    if (user?.username == null) {
      context.push('/register_nickname');
      return false;
    }
    if (user?.sex == null) {
      context.push('/register_sex');
      return false;
    }
    if (user?.birthday == null) {
      context.push('/register_birthday');
      return false;
    }
    return true;
  }

  ///获取日期
  static String getFormatDate({required DateTime dateTime, String format = 'YYYY-MM-DD'}) {
    // 获取日期的各个部分
    String year = dateTime.year.toString();
    String month = dateTime.month.toString().padLeft(2, '0');
    String day = dateTime.day.toString().padLeft(2, '0');
    String hour = dateTime.hour.toString().padLeft(2, '0');
    String minute = dateTime.minute.toString().padLeft(2, '0');
    String second = dateTime.second.toString().padLeft(2, '0');

    // 根据格式拼接对应的部分
    return format
        .replaceAll('YYYY', year)
        .replaceAll('MM', month)
        .replaceAll('DD', day)
        .replaceAll('hh', hour)
        .replaceAll('mm', minute)
        .replaceAll('ss', second);
  }
  ///获取中文星期
  static String getDayOfWeek(DateTime date) {
    // 定义一个星期数组
    List<String> weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];

    // 使用 DateTime 的 weekday 属性获取今天的星期索引
    // 需要将索引 - 1 对应到数组中，注意 DateTime 的星期索引从 1 (星期一) 到 7 (星期日)
    return weekdays[date.weekday % 7];
  }

  /// 获取当前年份
  static int getCurrentYear() {
    return DateTime.now().year;
  }
  ///根据时间字符串提取其中的小时
  static String getHourByDate(String timeString) {
    if (timeString == '') {
      return '';
    }
    // 解析时间字符串
    DateTime dateTime = DateTime.parse(timeString);
    // 获取小时
    int hour = dateTime.toLocal().hour;
    late String result;
    if (hour >= 12 && hour <= 24) {
      result = '${hour}pm';
    } else {
      result = '${hour}am';
    }
    return result;
  }

  /// 获取星期几
  /// @param dateString 日期字符串，格式：2024-10-11
  /// @return 返回 "今天" 或 "周一" 到 "周日"
  static String getWeekDay(String dateString) {
    if (dateString.isEmpty) return '';

    // 解析日期字符串
    DateTime date = DateTime.parse(dateString);
    DateTime now = DateTime.now();
    
    // 判断是否是今天
    if (date.year == now.year && date.month == now.month && date.day == now.day) {
      return '今天';
    }

    // 返回周几
    switch (date.weekday) {
      case 1:
        return '周一';
      case 2:
        return '周二';
      case 3:
        return '周三';
      case 4:
        return '周四';
      case 5:
        return '周五';
      case 6:
        return '周六';
      case 7:
        return '周日';
      default:
        return '';
    }
  }

  ///转换多媒体上传需要的全日期
  static String formatFullDate(DateTime date) {
    final year = date.year;
    final month = date.month;
    final day = date.day;
    String result = '$year${month.toString().padLeft(2, '0')}${day.toString().padLeft(2, '0')}';
    return result;
  }

  //判断图片是否超过规定的最大值:10MB
  static bool isPictureInMaxSize(int fileSize) {
    if (fileSize > 1024 * 1024 * 10) {
      EasyLoading.showToast('图片不得超过10MB');
      return false;
    }
    return true;
  }

  /// 根据生日获取生肖属性的index (0-11)
  /// 生肖顺序：鼠(0)、牛(1)、虎(2)、兔(3)、龙(4)、蛇(5)、马(6)、羊(7)、猴(8)、鸡(9)、狗(10)、猪(11)
  /// @param birthday 生日字符串，格式：yyyy-MM-dd
  /// @return 返回生肖index (0-11)
  static int getZodiacIndex(String birthday) {
    if (birthday.isEmpty) return 0;
    
    DateTime birthDate = DateTime.parse(birthday);
    // 转换为农历年
    Lunar lunar = Lunar.fromDate(birthDate);
    int lunarYear = lunar.getYear();
    
    return ((lunarYear - 1900) % 12 + 12) % 12;
  }

  static getZodiacTxtBybIndex(int index) {
    final animals = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'];
    return animals[index];
  }
  static getZodiacPinYinBybIndex(int index) {
    final animals = ['shu', 'niu', 'hu', 'tu', 'long', 'she', 'ma', 'yang', 'hou', 'ji', 'gou', 'zhu'];
    return animals[index];
  }

  /// 通用对象合并方法
  /// 将 source 对象的非空属性合并到 target 对象中
  /// S 必须是 T 的子类型，两者都必须实现 toJson() 和 fromJson() 方法
  static void mergeObjects<T, S extends T>(T target, S source) {
    if (target == null || source == null) return;

    // 获取源对象的 JSON Map
    final sourceJson = (source as dynamic).toJson();
    // 获取目标对象的 JSON Map
    final targetJson = (target as dynamic).toJson();

    // 只合并源对象中非空的值
    sourceJson.forEach((key, value) {
      if (value != null) {
        targetJson[key] = value;
      }
    });

    // 将合并后的数据更新回目标对象
    (target as dynamic).fromJson(targetJson);
  }

  /// 计算指定日期与今天的差距
  /// @param dateString 日期字符串，格式：yyyy-MM-dd
  /// @return 返回 "X天前" 或 "X天后" 或 "今天"
  static String getDaysFromNow(String dateString) {
    if (dateString.isEmpty) return '';
    try {
      final date = DateTime.parse(dateString);
      final now = DateTime.now();
      
      // 去除时分秒，只比较年月日
      final targetDate = DateTime(date.year, date.month, date.day);
      final today = DateTime(now.year, now.month, now.day);
      
      // 计算日期差
      final difference = targetDate.difference(today).inDays;
      
      if (difference == 0) {
        return '今天';
      } else if (difference > 0) {
        return '$difference天后';
      } else {
        return '${difference.abs()}天前';
      }
    } catch (e) {
      return '';
    }
  }

  /// 将中文节气转换为拼音
  /// @param solarTerm 中文节气名称
  /// @return 返回对应的拼音
  static String getSolarTermPinyin(String solarTerm) {
    final Map<String, String> solarTermPinyinMap = {
      '立春': 'lichun',
      '雨水': 'yushui',
      '惊蛰': 'jingzhe',
      '春分': 'chunfen',
      '清明': 'qingming',
      '谷雨': 'guyu',
      '立夏': 'lixia',
      '小满': 'xiaoman',
      '芒种': 'mangzhong',
      '夏至': 'xiazhi',
      '小暑': 'xiaoshu',
      '大暑': 'dashu',
      '立秋': 'liqiu',
      '处暑': 'chushu',
      '白露': 'bailu',
      '秋分': 'qiufen',
      '寒露': 'hanlu',
      '霜降': 'shuangjiang',
      '立冬': 'lidong',
      '小雪': 'xiaoxue',
      '大雪': 'daxue',
      '冬至': 'dongzhi',
      '小寒': 'xiaohan',
      '大寒': 'dahan'
    };

    return solarTermPinyinMap[solarTerm] ?? solarTerm;
  }

  ///通过角度获取方位
  static String getCompassStation(double direction) {
    // 将 direction 限制在 0° - 360° 范围内
    direction = direction % 360;
    if (direction < 22.5 || direction >= 337.5) {
      return 'znxb';//坐南向北
    } else if (direction >= 22.5 && direction < 67.5) {
      return 'zxnxdb';//坐西南向东北
    } else if (direction >= 67.5 && direction < 112.5) {
      return 'zxxd';//坐西向东
    } else if (direction >= 112.5 && direction < 157.5) {
      return 'zxbxdn';//坐西北向东南
    } else if (direction >= 157.5 && direction < 202.5) {
      return 'zbxn';//坐北向南
    } else if (direction >= 202.5 && direction < 247.5) {
      return 'zdbxxn';//坐东北向西南
    } else if (direction >= 247.5 && direction < 292.5) {
      return 'zdxx';//坐东向西
    } else {
      return 'zdnxxb';//坐东南向西北
    }
  }

  ///解析日期 2024-12-12
  static DateTime parseDate(String dateStr) {
    // 将格式为 'YYYY-MM-DD' 的字符串转换为 DateTime 对象
    List<String> dateParts = dateStr.split('-');
    int year = int.parse(dateParts[0]);
    int month = int.parse(dateParts[1]);
    int day = int.parse(dateParts[2]);

    return DateTime(year, month, day);
  }
  ///解析中文日期 2024年12月12日
  static DateTime? parseChineseDate(String dateStr) {
    // 使用正则表达式提取年月日
    final RegExp regExp = RegExp(r'(\d{4})年(\d{1,2})月(\d{1,2})日');
    final match = regExp.firstMatch(dateStr);

    if (match != null) {
      int year = int.parse(match.group(1)!);
      int month = int.parse(match.group(2)!);
      int day = int.parse(match.group(3)!);

      // 返回对应的 DateTime 对象
      return DateTime(year, month, day);
    } else {
      return null;
    }
  }
  ///比较两个日期(2024年12月12日 2024-12-12)
  static bool compareDates(String chineseDate, String dateStr) {
    // 将两个日期字符串转换为 DateTime 对象
    DateTime? date1 = parseChineseDate(chineseDate);
    DateTime date2 = parseDate(dateStr);

    // 比较两个日期，如果 ChineseDate 小于或等于传入的日期，则返回 true
    return (date1 == null) ? false : (date1.isBefore(date2) || date1.isAtSameMomentAs(date2));
  }
  ///获取十二时辰
  static Map<String, String> getLunarTime(DateTime now) {
    Lunar lunar = Solar.fromDate(now).getLunar();
    // 获取干支信息
    String ganZhiYear = lunar.getYearInGanZhi(); // 干支年
    String ganZhiMonth = lunar.getMonthInGanZhi(); // 干支月
    String ganZhiDay = lunar.getDayInGanZhi(); // 干支日

    // 获取时辰的地支
    String hm = '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
    int timeZhiIndex = LunarUtil.getTimeZhiIndex(hm) + 1; // 时辰地支序号
    String timeZhi = LunarUtil.ZHI[timeZhiIndex]; // 地支名

    // 计算时辰天干
    int dayGanIndex = lunar.getDayGanIndex(); // 日干序号
    int timeGanIndex = (dayGanIndex * 2 + timeZhiIndex) % 10; // 时干序号
    String timeGan = LunarUtil.GAN[timeGanIndex]; // 天干名

    // 拼接时辰干支
    String ganZhiTime = '$timeGan$timeZhi';

    return {
      'ganZhiYear': ganZhiYear,
      'ganZhiMonth': ganZhiMonth,
      'ganZhiDay': ganZhiDay,
      'ganZhiTime': ganZhiTime,
    };
  }

  ///获取星座
  static String getZodiacSign(DateTime birthDate) {
    int month = birthDate.month;
    int day = birthDate.day;

    // 星座日期范围及其对应的英文名称
    if ((month == 3 && day >= 21) || (month == 4 && day <= 19)) {
      return "aries";
    } else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) {
      return "taurus";
    } else if ((month == 5 && day >= 21) || (month == 6 && day <= 20)) {
      return "gemini";
    } else if ((month == 6 && day >= 21) || (month == 7 && day <= 22)) {
      return "cancer";
    } else if ((month == 7 && day >= 23) || (month == 8 && day <= 22)) {
      return "leo";
    } else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) {
      return "virgo";
    } else if ((month == 9 && day >= 23) || (month == 10 && day <= 22)) {
      return "libra";
    } else if ((month == 10 && day >= 23) || (month == 11 && day <= 21)) {
      return "scorpio";
    } else if ((month == 11 && day >= 22) || (month == 12 && day <= 21)) {
      return "sagittarius";
    } else if ((month == 12 && day >= 22) || (month == 1 && day <= 19)) {
      return "capricorn";
    } else if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) {
      return "aquarius";
    } else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) {
      return "pisces";
    } else {
      return '';
    }
  }

  //震动插件
  static Future shake({int amplitude = 4}) async {
    final bool support = await Vibration.hasCustomVibrationsSupport() ?? false;
    if (!support) return;
    try {
      await Vibration.cancel();
      Vibration.vibrate(pattern: [1, amplitude], intensities: [1, 255]);
    } catch (e) {
      rethrow;
    }
  }

}